/*
* SSAFormFilter.cpp: Impletement class SSAFormFilter.
* The main function of this cpp file is to convert vinsts to SSA Form
* By: CrossBit Group, vivy. 2008-3-31 .
*/

#include "crossbit/VFilter.h"
#include "crossbit/VInst.h"

using namespace crossbit;

//count for vregisters
XTInt32 total_vreg = 1;

XTUint32 SSAFormFilter::run(VBlock *vb)
{
  XTInt32 has_SSA = 1;
  VBlock::iterator I = vb->begin(),
           E = vb->end();
  
  //rn_tbl is a rename table
  XTRegNum rn_tbl[5] = {0};
  XTRegNum n_vreg = 1;
  
  for(; I != E; I++)
  {
     VInst *inst = *I;
     Opcode op = inst->getOpcode();
     //If vinst is a float inst, then we do not do SSA form for this VBlock
     if((op == OP_ST) || (op == OP_FPUT_S) || (op == OP_FGET_S) || (op == OP_FPUT_D) || (op ==  OP_FGET_D) || (op == OP_FLD) || (op == OP_FST) || (op == OP_FMOV) || (op == OP_FADD_S) || (op == OP_FADD_D) || (op == OP_FSUB_S) || (op == OP_FSUB_D) || (op == OP_FMUL_S) || (op == OP_FMUL_D) || (op == OP_FDIV_S) || (op == OP_FDIV_D) || (op == OP_FNEG_S) || (op == OP_FNEG_D) || (op == OP_FABS_S) || (op == OP_FABS_D) || (op == OP_FSQRT_S) || (op == OP_FSQRT_D) || (op == OP_FCMP_S) || (op == OP_FCMP_D) || (op == OP_FCONV) || (op == OP_FINCSTP)) {
		has_SSA = 0;
		break;
	 }
  }
  
  if(has_SSA == 1)
  {
      I = vb->begin();
      for(; I != E; I++)
      {
          VInst *inst = *I;
          XTInt32 n = inst->getOperandNum();            //Get operand number
          
          //Handle with all the operand
          for(XTInt32 i=1; i<=n; i++)
          {
              Operand oprnd = inst->getOperand(i);  //Get the ith operand
              
              if(oprnd.type == Operand::VREG_USE && oprnd.reg > 0)
              {
                  oprnd.reg = rn_tbl[oprnd.reg];   //Get it from rename table
                  inst->setOperand(i, oprnd);      //Update the current inst
              }
              else if(oprnd.type == Operand::VREG_DEF)
              {
                  assert(oprnd.reg > 0);
                  rn_tbl[oprnd.reg] = n_vreg;      //Put it into rename table
                  oprnd.reg = n_vreg;
                  inst->setOperand(i, oprnd);      //Update the current inst
                  n_vreg++;                        
              }
          }//end for(int i=1; i<=n; i++)
                 
      }//end for(; I != E; I++)
  }//end is((has_SSA == 1)
  
  return (XTUint32)has_SSA;
}

